//    Copyright (C) Kherty.  All rights reserved.
using System.Collections.Generic;

namespace OpenLS.Spreadsheet.AnalysisToolPak
{
    internal class Units
    {
        private static List<UnitBase> _units;
        private static Dictionary<string, UnitBase> unitTable;

        private static List<UnitBase> UnitsList
        {
            get
            {
                if (_units == null)
                {
                    _units = new List<UnitBase>();
                    {
                        Unit meter = new Unit("m");
                        AddUnit(meter, true);
                        Unit inch = new Unit("in", 25400000e-9, meter);
                        AddUnit(inch, false);
                        Unit foot = new Unit("ft", inch.Factor*12, meter);
                        AddUnit(foot, false);
                        Unit yard = new Unit("yd", 9.14400000300000000000000000000000000E-01, meter);
                        AddUnit(yard, false);
                        Unit mile = new Unit("mi", 1609.3440000000000000000000, meter);
                        AddUnit(mile, false);
                        AddUnit(new Unit("ang", 1e-10, meter), false);
                        AddUnit(new Unit("Pica", 3.52777777777800000000000000000000E-04, meter), false);
                        AddUnit(new Unit("Nmi", 1.852E3, meter), false);
                    }
                    {
                        Unit gram = new Unit("g");
                        AddUnit(gram, true);
                        AddUnit(new Unit("sg", 14593.84241892870000000000000, gram), false);
                        AddUnit(new Unit("lbm", 453.59230974881100000000000, gram), false);
                        AddUnit(new Unit("u", 1.660531004604650000000000E-24, gram), false);
                        AddUnit(new Unit("ozm", 28.34951520797320000000000, gram), false);
                    }

                    {
                        Unit liter = new Unit("l");
                        AddUnit(liter, true);
                        AddUnit(new Unit("tsp", 4.92999408400710000000000000000E-03, liter), false);
                        AddUnit(new Unit("tbs", 1.47899822520213000000000000000E-02, liter), false);
                        AddUnit(new Unit("oz", 2.95799645040426000000000000000E-02, liter), false);
                        AddUnit(new Unit("cup", 2.36639716032341000000000000000E-01, liter), false);
                        AddUnit(new Unit("pt", 4.73279432064682000000000000000E-01, liter), false);
                        AddUnit(new Unit("qt", 9.46558864129363000000000000000E-01, liter), false);
                        AddUnit(new Unit("gal", 3.78623545651745000000000000000E+00, liter), false);
                        AddUnit(new Unit("us_pt", 4.73279432064682000000000000000E-01, liter), false);
                        AddUnit(new Unit("uk_pt", 5.68260698087162000000000000000E-01, liter), false);
                        AddUnit(new Unit("lt", 1, liter), false);
                    }

                    {
                        Unit joule = new Unit("J");
                        AddUnit(joule, true);
                        AddUnit(new Unit("e", 100.0000480657e-9, joule), true);
                        AddUnit(new Unit("c", 4183991013.63672e-9, joule), true);
                        AddUnit(new Unit("cal", 4186794846.13929e-9, joule), true);
                        AddUnit(new Unit("eV", 1.60219000146921E-19, joule), true);
                        AddUnit(new Unit("HPh", 2684517413161700e-9, joule), false);
                        AddUnit(new Unit("Wh", 3599998205547.2e-9, joule), true);
                        AddUnit(new Unit("flb", 42140000.3236424e-9, joule), false);
                        AddUnit(new Unit("BTU", 1055058137867.49e-9, joule), false);
                    }
                    {
                        Unit second = new Unit("sec");
                        AddUnit(second, true);
                        AddUnit(new Unit("yr", 31557600000000000e-9, second), false);
                        AddUnit(new Unit("day", 86400000000000e-9, second), false);
                        AddUnit(new Unit("hr", 3600000000000e-9, second), false);
                        AddUnit(new Unit("mn", 60000000000e-9, second), false);
                    }
                    {
                        Unit watt = new Unit("W");
                        AddUnit(watt, true);
                        AddUnit(new Unit("HP", 745701000000e-9, watt), false);
                    }
                    {
                        Unit pascal = new Unit("Pa");
                        AddUnit(pascal, true);
                        AddUnit(new Unit("atm", 101324996583000e-9, pascal), false);
                        AddUnit(new Unit("at", 101324996583000e-9, pascal), false);
                        AddUnit(new Unit("1", 1, pascal), false);
                        AddUnit(new Unit("mmHg", 133322363925e-9, pascal), false);
                    }
                    {
                        Unit newton = new Unit("N");
                        AddUnit(newton, true);
                        AddUnit(new Unit("dyn", 10000e-9, newton), true);
                        AddUnit(new Unit("lbf", 4448222000e-9, newton), false);
                    }
                    {
                        Unit tesla = new Unit("T");
                        AddUnit(tesla, true);
                        Unit gauss = new Unit("ga", 100000e-9, tesla);
                        AddUnit(gauss, true);
                    }
                    {
                        AddUnit(new Kelvin(), false);
                        AddUnit(new Celsius(), false);
                        AddUnit(new Farenheit(), false);
                    }
                }
                return _units;
            }
        }

        public static Dictionary<string, UnitBase> UnitTable
        {
            get
            {
                if (unitTable == null)
                {
                    unitTable = new Dictionary<string, UnitBase>();
                    foreach (UnitBase u in UnitsList)
                        unitTable.Add(u.Name, u);
                }
                return unitTable;
            }
        }

        private static void AddUnit(UnitBase u, bool withMultipliers)
        {
            _units.Add(u);
            if (withMultipliers)
            {
                foreach (Multiplier m in Multiplier.GetAll())
                    AddUnit(new Unit(m, (Unit) u), false);
            }
        }

        public static UnitBase GetUnit(string name)
        {
            UnitBase result = null;
            UnitTable.TryGetValue(name, out result);
            return result;
        }
    }
}